package com.silence.gmall.aop;

import brave.Span;
import brave.Tracing;
import com.silence.gmall.handler.LoggerHandler;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobHelper;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.MDC;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @Author silence
 * @Date 2025-09-08 14:07
 * @Email 792245022@qq.com
 * @Version 1.0
 * @Description
 */
@Aspect
@Order(100)
@Component
@RequiredArgsConstructor
public class XxlJobLogAop {

    /**
     * 日志注入
     */
    private static final Logger log = LoggerHandler.createLogger(XxlJobLogAop.class);

    /**
     * 跟踪器，用于获取当前请求的跟踪信息
     */
    private final Tracing tracing;

    /**
     * 定义切点，拦截所有标注了 @XxlJob 的方法，或者你可以选择其他条件
     */
    @Pointcut("@annotation(com.xxl.job.core.handler.annotation.XxlJob)")
    public void jobMethods() {
    }

    /**
     * 环绕通知，增强控制器响应
     *
     * @param joinPoint 连接点
     * @return 原始或增强后的结果
     */
    @Around("jobMethods()")
    public Object enhanceResponse(ProceedingJoinPoint joinPoint) {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        String methodName = method.getName();
        String className = method.getDeclaringClass().getSimpleName();
        String fullMethodPath = className + "#" + methodName;

        // 获取当前 span
        Span currentSpan = tracing.tracer().currentSpan();
        if (Objects.isNull(currentSpan)) {
            currentSpan = tracing.tracer().newTrace();
        }
        String traceId = currentSpan.context().traceIdString();
        String spanId = currentSpan.context().spanIdString();

        // 将 traceId 和 spanId 放入 MDC，日志中可以自动显示
        MDC.put("traceId", traceId);
        MDC.put("spanId", spanId);

        String jobParam = XxlJobHelper.getJobParam();
        log.info("【{}】 - 定时任务调用开始，【traceId：{}】 - 【spanId：{}】", fullMethodPath, traceId, spanId);
        log.info("【{}】 - 入参打印：{}", fullMethodPath, jobParam);

        // 计时
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // 执行目标方法
        Object result;
        try {
            // 调用目标方法
            result = joinPoint.proceed();
            log.info("【{}】 - 返回结果：{}", fullMethodPath, result);
        } catch (Throwable te) {
            log.error("定时任务调用异常：", te);
            return ReturnT.FAIL;
        } finally {
            stopWatch.stop();
            log.info("【{}】 - 耗时：{} ms", fullMethodPath, stopWatch.getTotalTimeMillis());
            log.info("【{}】 - 定时任务调用结束", fullMethodPath);

            MDC.remove("traceId");
            MDC.remove("spanId");
        }
        return result;
    }
}
